<template>
  <!-- 使用过渡效果包裹消息组件 -->
  <!-- 离开动画结束后执行销毁组件方法 -->
  <!-- 进入动画开始时执行更新高度方法 -->
   <Transition 
    name="fade-up" 
    @after-leave="destoryComponent" 
    @enter="updateHeight">
    <!-- 根据 visible 控制消息是否显示 -->
    <!-- 鼠标移入时清除定时器，鼠标移出时启动定时器 -->
     <div 
      class="rl-message"
      v-show="visible"
      :class="{
        [`rl-message--${type}`]:type,
        'is-close':showClose
      }"
      role="alert"
      ref="messageRef"
      :style="cssStyle"
      @mouseenter="clearTimer"
      @mouseleave="startTimer"
    >
      <div class="rl-message--content">
        <slot>
          <!-- 渲染消息内容 -->
           <RenderVnode :vNode="message" v-if="message"></RenderVnode>
        </slot>
      </div>  
        <div class="rl-message--close" v-if="showClose">
          <!-- 显示关闭按钮 -->
          <RlIcon @click.stop="visible=false" icon="xmark"></RlIcon> <!-- 点击关闭按钮后隐藏消息 -->
        </div>
    </div>
     
   </Transition>

</template>

<script setup lang="ts">
import { computed, onMounted, ref } from 'vue';
import { type MessageProps } from './types';
import { getLastBottomOffset } from './method';
import RenderVnode from '../RenderVnode';
import RlIcon from '@/components/Icon/Icon.vue'
import useEventListener from '@/hooks/useEventListener';


defineOptions({
  name: 'RlMessage'
})
// 使用props定义消息组件的属性
const props = withDefaults(defineProps<MessageProps>(),{
  type: 'info',
  duration: 3000,  //3000ms
  offset: 20
})
// 使用ref创建响应式变量
const visible = ref(false)     //消息是否可见
const messageRef = ref<HTMLDivElement>()    //消息组件的引用

// 计算属性
const height = ref(0)     //计算组件高度
const lastOffset = computed(()=>getLastBottomOffset(props.id))   // 上一个实例的最下面的坐标数字
const topOffset = computed(()=>props.offset + lastOffset.value)   // 元素的 top 偏移量
const bottomOffset = computed(()=>height.value + topOffset.value)   // 元素的 bottom 偏移量，为下一个消息组件提供
const cssStyle = computed(()=>({
  top: topOffset.value + 'px',
  zIndex: props.zIndex
}))

// 定时器相关
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let timer:any 
function startTimer(){
  if(props.duration === 0) return
  timer = setTimeout(()=>{
    visible.value = false   //定时器结束后隐藏消息
  },props.duration)
}
// 清除定时器
function clearTimer(){
  clearTimeout(timer)
}
// 组件生命周期钩子
onMounted(async ()=>{
  visible.value = true
  startTimer()
})
// 键盘事件处理函数
function keydown(e:Event){
  const event = e as KeyboardEvent
  if(event.code === 'Escape'){
    visible.value = false  //按下 Esc 键隐藏消息
  }
}
// 监听键盘事件
useEventListener(document,'keydown', keydown)

// 销毁组件函数
function destoryComponent(){
  props.onDestory()
}

// 更新高度函数
function updateHeight(){
  height.value = messageRef.value!.getBoundingClientRect().height
}


defineExpose({
  visible,
  bottomOffset
})
</script>